package org.workplicity.marist.grounds.util;

import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import org.workplicity.entry.*;
import org.workplicity.entry.event.Event;
import org.workplicity.task.NetTask;
import org.workplicity.util.Helper;
import org.workplicity.worklet.WorkletContext;

/**
 *
 * @author Elliott and steve
 */
public class Controller {
    //line 37 is the begininng of what each group must prepare
    // also the methods called should report their output to the report class
    // loadTestRepos is used so that we can test methods on controlled repositories

    public static ArrayList accounts = new ArrayList();
    public static ArrayList clearingHouse = new ArrayList();
    public static ArrayList futures = new ArrayList();
    public static ArrayList services = new ArrayList();
    public static ArrayList workSlates = new ArrayList();
    private static WorkletContext context = WorkletContext.getInstance();
    private static ArrayList<WorkRequest> oldClosedRequestsToBePurged = new ArrayList();
    private static ArrayList<WorkRequest> requestsNotOnWorkSlateToBePurged = new ArrayList();
    private static ArrayList<Event> oldFuturesToBePurged = new ArrayList();
    private static ArrayList<Event> futuresWithInvalidTemplateToBePurged = new ArrayList();

    /** Responsible for updating the local copy of the repositories
     * @param whichRepos[i] is whether or not repository i needs to be updates, in the order listed above (Alphabetical)
     */
    public static void updateRepos(boolean[] whichRepos) {
        //Report.init();
        if (whichRepos[0]) {
            accounts = Helper.query(NetTask.REPOS_ACCOUNTS, "/ list", context);
        }
        if (whichRepos[1]) {
            clearingHouse = Helper.query(NetTask.REPOS_CLEARINGHOUSE, "/ list", context);
        }
        if (whichRepos[2]) {
            futures = Helper.query(NetTask.REPOS_FUTURES, "/ list", context);
        }
        if (whichRepos[3]) {
            services = Helper.query(NetTask.REPOS_SERVICES, "/ list", context);
        }
        if (whichRepos[4]) {
            workSlates = Helper.query(NetTask.REPOS_WORKSLATES, "/ list", context);
        }
    }

    /**
     * calls updateRepos in order to retrieve all repositories
     */
    public static void updateRepos() {
        boolean[] allTrue = {true, true, true, true, true};
        updateRepos(allTrue);
    }

    /** 
     * loads user created repository values for testing purposes
     */
    public static void loadTestRepos() {
        clearingHouse = new ArrayList<WorkRequest>();
        futures = new ArrayList<Event>();
        services = new ArrayList<Service>();
        workSlates = new ArrayList<WorkSlate>();
        accounts = new ArrayList<User>();
        accounts.add(new User("elliott", "abc123"));
        accounts.add(new User("steve", "ok"));
        accounts.add(new User("elliott", "abc123"));
        User steve = new User("st3v3", "password");
        accounts.add(steve);
    }

    /** 
     * Calls appropriate repair methods depending on which checkboxes are checked
     * @param repairChecks[i] is a boolean representing whether or not the ith check box is checked
     */
    public static void repair(boolean[] repairChecks, long start, long end) {
        final boolean[] localChecks = new boolean[]{repairChecks[0],
            repairChecks[1],
            repairChecks[2],
            repairChecks[3],
            repairChecks[4],
            repairChecks[5],
            repairChecks[6]};

        final long startDate = start;
        final long endDate = end;

//      JOptionPane waitingWindow = new JOptionPane("Repairing...");
//      waitingWindow.setOptions(new Object[0]);
//      waitingWindow.setMessageType(JOptionPane.INFORMATION_MESSAGE);

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                Repair.setGlobals(startDate, endDate);

                if (accounts == null) {
                    accounts = Helper.query(NetTask.REPOS_ACCOUNTS, "/ list", context);
                }
                if (workSlates == null) {
                    workSlates = Helper.query(NetTask.REPOS_WORKSLATES, "/ list", context);
                }
                if (services == null) {
                    services = Helper.query(NetTask.REPOS_SERVICES, "/ list", context);
                }

                if (localChecks[0]) {
                    accounts = Repair.fixInvalidCreateDate(accounts, 1);
                    clearingHouse = Repair.fixInvalidCreateDate(clearingHouse, 2);
                    workSlates = Repair.fixInvalidCreateDate(workSlates, 3);
                    services = Repair.fixInvalidCreateDate(services, 4);
                    futures = Repair.fixInvalidCreateDate(futures, 5);
                }

                if (localChecks[1]) {
                    accounts = Repair.fixInvalidUpdateDate(accounts, 1);
                    clearingHouse = Repair.fixInvalidUpdateDate(clearingHouse, 2);
                    futures = Repair.fixInvalidUpdateDate(futures, 5);
                    services = Repair.fixInvalidUpdateDate(services, 4);
                    workSlates = Repair.fixInvalidUpdateDate(workSlates, 3);
                }

                if (localChecks[2]) {
                    accounts = Repair.fixInvalidUpdateUser(accounts, accounts, 1);
                    clearingHouse = Repair.fixInvalidUpdateUser(clearingHouse, accounts, 2);
                    futures = Repair.fixInvalidUpdateUser(futures, accounts, 5);
                    services = Repair.fixInvalidUpdateUser(services, accounts, 4);
                    workSlates = Repair.fixInvalidUpdateUser(workSlates, accounts, 3);
                }

                if (localChecks[3]) {
                    accounts = Repair.fixInvalidWorkSlateReferences(accounts, workSlates, 1);
                }
                if (localChecks[4]) {
                    accounts = Repair.fixInvalidServiceReferences(accounts, services, 1);
                }
                if (localChecks[5]) {
                    accounts = Repair.fixDuplicateWorkSlateReferences(accounts, 1);
                }
                if (localChecks[6]) {
                    accounts = Repair.fixDuplicateServiceReferences(accounts, 1);
                }

                Repair.writeBackDirties();
            }
        });
    }

    /**
     * This method determines which repositories needs to be retrieved. Then
     * it calls the appropriate purge methods based on what check boxes the user
     * selected.
     * @param purgeChecks is an array of booleans for the check boxes on the
     * purge tab
     * @param olderThan is a long representing either 1 day, week, month, or
     * year
     */
    public static void purge(boolean[] purgeChecks, long startDate, long endDate) {
        final boolean[] localChecks = new boolean[]{purgeChecks[0],
            purgeChecks[1],
            purgeChecks[2],
            purgeChecks[3]};

        //Date parameters have to be assigned to local variables that are final
        //in order to be used in the thread
        final long localStartDate = startDate;
        final long localEndDate = endDate;

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                //Declare boolean array to be sent to updateRepos
                boolean[] getReposNeeded = new boolean[5];

                if (localChecks[0]) {
                    //Set array index for clearingHouse and Workslate to true
                    //Clearinghouse
                    getReposNeeded[1] = true;
                    //WorkSlates
                    getReposNeeded[4] = true;
                    //Call updatesRepos on boolean array to retrieve repositories
                    updateRepos(getReposNeeded);

                    requestsNotOnWorkSlateToBePurged = Purge.getRequestsNotOnWorkslate(clearingHouse, workSlates);
                }
                if (localChecks[1]) {
                    //Check to see if the workSlates repository has already been
                    //retrieved, if not, set appropriate index to true and call
                    //updateRepos
                    if (!getReposNeeded[1]) {
                        getReposNeeded[1] = true;
                        updateRepos(getReposNeeded);
                    }
                    oldClosedRequestsToBePurged = Purge.getOldClosedRequests(localStartDate, localEndDate, clearingHouse);
                }
                if (localChecks[2]) {
                    //Set index for future repository to true
                    getReposNeeded[2] = true;
                    //Call update repos to retrieve futures repository
                    updateRepos(getReposNeeded);
                    futuresWithInvalidTemplateToBePurged = Purge.getFuturesWithInvalidTemplate(futures);
                }
                if (localChecks[3]) {
                    //Check to see if the futures repository has already been retrieved
                    //if not, set appropriate index to true and call updateRepos
                    if (!getReposNeeded[2]) {
                        getReposNeeded[2] = true;
                        updateRepos(getReposNeeded);
                    }

                    oldFuturesToBePurged = Purge.getOldFutureEvents(localStartDate, localEndDate, futures);
                }

                purgeRepositories();



            }
        });
    }

    /** 
     * Calls appropriate warn methods depending on which checkboxes are checked
     * @param repairChecks[i] is a boolean representing whether or not the ith check box is checked
     */
    public static void warn(boolean[] warnChecks) {
        final boolean[] localChecks = new boolean[]{warnChecks[0],
            warnChecks[1],
            warnChecks[2],
            warnChecks[3],
            warnChecks[4],
            warnChecks[5],
            warnChecks[6],
            warnChecks[7],
            warnChecks[8]};

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                JFrame frame = new JFrame("Warning check in progress...");
                JProgressBar progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
                progressBar.setStringPainted(true);
                progressBar.setIndeterminate(true);
                frame.add(progressBar);
                frame.setSize(300, 100);
                frame.setVisible(true);
                if (localChecks[0]) {
                    Warn.checkServiceNoUser(services, accounts);
                }
                if (localChecks[1]) {
                    Warn.checkUserNoService(accounts);
                }
                if (localChecks[2]) {
                    Warn.futuresInvalidTemplates(futures);
                }
                if (localChecks[3]) {
                    Warn.enabledAndExpired(futures);
                }
                if (localChecks[4]) {
                    Warn.checkDuplicateNames(accounts);
                }
                if (localChecks[5]) {
                    Warn.duplicateIds(clearingHouse, services, workSlates, accounts, futures);
                }
                if (localChecks[6]) {
                    Warn.ReqsWithInvalidServices(clearingHouse, services);
                }
                if (localChecks[7]) {
                    Warn.invalidLogname(accounts);
                }
                if (localChecks[8]) {
                    Warn.invalidPassword(accounts);
                }
                frame.setVisible(false);
                JOptionPane.showMessageDialog(null, Report.getNumWarnings() + " warning(s) have been added to the report.", "Actions taken", JOptionPane.WARNING_MESSAGE);
            }
        });
    }

    /**
     * This method calls the corresponding purge method to delete entries
     * from repositories based on if the array list is not empty
     */
    public static void purgeRepositories() {

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                if (!oldClosedRequestsToBePurged.isEmpty()) {
                    Purge.purgeOldClosedRequests(oldClosedRequestsToBePurged);
                    oldClosedRequestsToBePurged.clear();
                }
                if (!requestsNotOnWorkSlateToBePurged.isEmpty()) {
                    Purge.purgeRequestsNotOnWorkSlate(requestsNotOnWorkSlateToBePurged);
                    requestsNotOnWorkSlateToBePurged.clear();
                }
                if (!oldFuturesToBePurged.isEmpty()) {
                    Purge.purgeOldFutureEvents(oldFuturesToBePurged);
                    oldFuturesToBePurged.clear();
                }
                if (!futuresWithInvalidTemplateToBePurged.isEmpty()) {
                    Purge.purgeFuturesWithInvalidTemplate(futuresWithInvalidTemplateToBePurged);
                    futuresWithInvalidTemplateToBePurged.clear();
                }

                JOptionPane.showMessageDialog(null, Report.getNumPurged()
                        + " purge(s) have been performed and were added to the report.",
                        "Actions taken", JOptionPane.WARNING_MESSAGE);
            }
        });
    }
}
